package dao

import (
	"context"
	"fmt"
	"order_srv/basic/config"
	"order_srv/handler/models"
	"time"

	"gorm.io/gorm"
)

// CreateOrder 创建订单（包含完整的业务逻辑和校验）
func CreateOrder(ctx context.Context, order *models.Order) error {
	// 1. 参数校验
	if err := validateOrder(order); err != nil {
		return err
	}

	// 2. 校验订单明细
	if len(order.Items) == 0 {
		return fmt.Errorf("订单明细不能为空")
	}

	for i, item := range order.Items {
		if item.ItemName == "" {
			return fmt.Errorf("第%d个明细项名称不能为空", i+1)
		}
		if item.UnitPrice <= 0 {
			return fmt.Errorf("第%d个明细项单价必须大于0", i+1)
		}
		if item.Quantity <= 0 {
			return fmt.Errorf("第%d个明细项数量必须大于0", i+1)
		}
		if item.ItemType < 1 || item.ItemType > 6 {
			return fmt.Errorf("第%d个明细项类型无效", i+1)
		}
	}

	return config.DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		// 1. 生成订单号
		order.OrderNo = generateOrderNo()

		// 2. 创建订单
		if err := tx.Create(order).Error; err != nil {
			return fmt.Errorf("创建订单失败: %w", err)
		}

		// 3. 创建订单明细
		for _, item := range order.Items {
			// 创建新的订单明细对象，避免ID冲突
			orderItem := &models.OrderItem{
				OrderID:          order.ID,
				ItemType:         item.ItemType,
				ItemName:         item.ItemName,
				ItemDesc:         item.ItemDesc,
				UnitPrice:        item.UnitPrice,
				Quantity:         item.Quantity,
				Amount:           item.UnitPrice * item.Quantity,
				BillingCycle:     item.BillingCycle,
				BillingStartDate: item.BillingStartDate,
				BillingEndDate:   item.BillingEndDate,
			}
			if err := tx.Create(orderItem).Error; err != nil {
				return fmt.Errorf("创建订单明细失败: %w", err)
			}
		}

		// 4. 记录订单状态日志
		log := &models.OrderStatusLog{
			OrderID:      order.ID,
			FromStatus:   -1, // 初始状态
			ToStatus:     order.OrderStatus,
			StatusType:   1, // 订单状态
			OperatorID:   order.TenantID,
			OperatorType: 1, // 租客
			Reason:       "订单创建",
			Remark:       "租客创建了新订单",
		}
		return tx.Create(log).Error
	})
}

// GetOrderByID 根据ID获取订单
func GetOrderByID(ctx context.Context, id uint64) (*models.Order, error) {
	if id == 0 {
		return nil, fmt.Errorf("订单ID不能为空")
	}

	var order models.Order
	err := config.DB.WithContext(ctx).
		Preload("Items").
		First(&order, id).Error

	if err != nil {
		return nil, err
	}
	return &order, nil
}

// GetOrdersByTenantID 根据租客ID获取订单列表
func GetOrdersByTenantID(ctx context.Context, tenantID string, page, pageSize int) ([]*models.Order, int64, error) {
	// 参数校验
	if tenantID == "" {
		return nil, 0, fmt.Errorf("租客ID不能为空")
	}
	page, pageSize = normalizePagination(page, pageSize)

	var orders []*models.Order
	var total int64

	query := config.DB.WithContext(ctx).Model(&models.Order{}).Where("tenant_id = ?", tenantID)

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	offset := (page - 1) * pageSize
	err := query.
		Preload("Items").
		Order("created_at DESC").
		Offset(offset).
		Limit(pageSize).
		Find(&orders).Error

	return orders, total, err
}

// GetOrdersByLandlordID 根据房东ID获取订单列表
func GetOrdersByLandlordID(ctx context.Context, landlordID string, page, pageSize int) ([]*models.Order, int64, error) {
	// 参数校验
	if landlordID == "" {
		return nil, 0, fmt.Errorf("房东ID不能为空")
	}
	page, pageSize = normalizePagination(page, pageSize)

	var orders []*models.Order
	var total int64

	query := config.DB.WithContext(ctx).Model(&models.Order{}).Where("landlord_id = ?", landlordID)

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	offset := (page - 1) * pageSize
	err := query.
		Preload("Items").
		Order("created_at DESC").
		Offset(offset).
		Limit(pageSize).
		Find(&orders).Error

	return orders, total, err
}

// UpdateOrderStatus 更新订单状态（包含完整的业务逻辑和校验）
func UpdateOrderStatus(ctx context.Context, orderID uint64, status int8, operatorID, operatorType, reason string) error {
	// 1. 参数校验
	if orderID == 0 {
		return fmt.Errorf("订单ID不能为空")
	}
	if operatorID == "" {
		return fmt.Errorf("操作人ID不能为空")
	}
	if status < 0 || status > 5 {
		return fmt.Errorf("无效的订单状态")
	}

	return config.DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		// 1. 获取当前订单状态
		var currentOrder models.Order
		if err := tx.First(&currentOrder, orderID).Error; err != nil {
			if err == gorm.ErrRecordNotFound {
				return fmt.Errorf("订单不存在，ID: %d", orderID)
			}
			return err
		}

		// 2. 验证状态转换是否合法
		if !isValidStatusTransition(currentOrder.OrderStatus, status) {
			return fmt.Errorf("无效的状态转换: %d -> %d", currentOrder.OrderStatus, status)
		}

		// 3. 更新订单状态
		if err := tx.Model(&models.Order{}).Where("id = ?", orderID).Update("order_status", status).Error; err != nil {
			return err
		}

		// 4. 记录状态变更日志
		log := &models.OrderStatusLog{
			OrderID:      orderID,
			FromStatus:   currentOrder.OrderStatus,
			ToStatus:     status,
			StatusType:   1, // 订单状态
			OperatorID:   operatorID,
			OperatorType: parseOperatorType(operatorType),
			Reason:       reason,
		}
		return tx.Create(log).Error
	})
}

// DeleteOrder 软删除订单（包含完整的业务逻辑和校验）
func DeleteOrder(ctx context.Context, orderID uint64) error {
	// 1. 参数校验
	if orderID == 0 {
		return fmt.Errorf("订单ID不能为空")
	}

	// 2. 检查订单状态
	order, err := GetOrderByID(ctx, orderID)
	if err != nil {
		return err
	}

	// 3. 只有已取消或已退款的订单才能删除
	if order.OrderStatus != 4 && order.OrderStatus != 5 {
		return fmt.Errorf("只有已取消或已退款的订单才能删除")
	}

	// 4. 软删除订单
	return config.DB.WithContext(ctx).Delete(&models.Order{}, orderID).Error
}

// GetOrderStatistics 获取订单统计信息
func GetOrderStatistics(ctx context.Context, tenantID, landlordID string, startDate, endDate time.Time) (map[string]interface{}, error) {
	stats := make(map[string]interface{})

	// 基础查询条件
	query := config.DB.WithContext(ctx).Model(&models.Order{})
	if tenantID != "" {
		query = query.Where("tenant_id = ?", tenantID)
	}
	if landlordID != "" {
		query = query.Where("landlord_id = ?", landlordID)
	}
	if !startDate.IsZero() {
		query = query.Where("created_at >= ?", startDate)
	}
	if !endDate.IsZero() {
		query = query.Where("created_at <= ?", endDate)
	}

	// 总订单数
	var totalOrders int64
	if err := query.Count(&totalOrders).Error; err != nil {
		return nil, err
	}
	stats["total_orders"] = totalOrders

	// 各状态订单数
	var statusCounts []struct {
		Status int8  `json:"status"`
		Count  int64 `json:"count"`
	}
	if err := query.Select("order_status as status, count(*) as count").Group("order_status").Scan(&statusCounts).Error; err != nil {
		return nil, err
	}
	stats["status_counts"] = statusCounts

	// 总金额
	var totalAmount float64
	if err := query.Select("COALESCE(SUM(total_amount), 0)").Scan(&totalAmount).Error; err != nil {
		return nil, err
	}
	stats["total_amount"] = totalAmount

	// 已支付金额
	var paidAmount float64
	if err := query.Select("COALESCE(SUM(paid_amount), 0)").Scan(&paidAmount).Error; err != nil {
		return nil, err
	}
	stats["paid_amount"] = paidAmount

	return stats, nil
}

// 业务逻辑辅助函数

// validateOrder 验证订单基本信息
func validateOrder(order *models.Order) error {
	if order.TenantID == "" || order.LandlordID == "" || order.PropertyID == "" || order.OrderType == 0 {
		return fmt.Errorf("参数不完整：租客ID、房东ID、房源ID和订单类型不能为空")
	}

	// 校验租期日期
	if order.LeaseStartDate.IsZero() || order.LeaseEndDate.IsZero() {
		return fmt.Errorf("租期开始日期和结束日期不能为空")
	}
	if order.LeaseStartDate.After(order.LeaseEndDate) {
		return fmt.Errorf("租期开始日期不能晚于结束日期")
	}

	// 校验订单类型
	if order.OrderType < 1 || order.OrderType > 5 {
		return fmt.Errorf("无效的订单类型")
	}

	// 校验总金额
	if order.TotalAmount <= 0 {
		return fmt.Errorf("订单总金额必须大于0")
	}

	return nil
}

// normalizePagination 标准化分页参数
func normalizePagination(page, pageSize int) (int, int) {
	if page <= 0 {
		page = 1
	}
	if pageSize <= 0 {
		pageSize = 10
	}
	if pageSize > 100 {
		pageSize = 100
	}
	return page, pageSize
}

// generateOrderNo 生成订单号
func generateOrderNo() string {
	return fmt.Sprintf("ORD%d", time.Now().UnixNano())
}

// isValidStatusTransition 验证状态转换是否合法
func isValidStatusTransition(fromStatus, toStatus int8) bool {
	// 定义允许的状态转换
	validTransitions := map[int8][]int8{
		0: {1, 4}, // 待确认 -> 已确认, 已取消
		1: {2, 4}, // 已确认 -> 进行中, 已取消
		2: {3, 4}, // 进行中 -> 已完成, 已取消
		3: {5},    // 已完成 -> 已退款
		4: {},     // 已取消 -> 无
		5: {},     // 已退款 -> 无
	}

	allowedStatuses, exists := validTransitions[fromStatus]
	if !exists {
		return false
	}

	for _, allowed := range allowedStatuses {
		if allowed == toStatus {
			return true
		}
	}
	return false
}

// parseOperatorType 解析操作人类型
func parseOperatorType(operatorType string) int8 {
	switch operatorType {
	case "tenant":
		return 1
	case "landlord":
		return 2
	case "agent":
		return 3
	case "system":
		return 4
	case "service":
		return 5
	default:
		return 4 // 默认为系统
	}
}
